/*
 * You may freely copy, distribute, and reuse the code in this example.
 * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
 * fitness for any particular use.
 */


#import "CellScrollView.h"
#import "FooCell.h"
#import <appkit/Matrix.h>
#import <objc/List.h>

@implementation CellScrollView

- init
{
  return [self initFrame:NULL];
}

- initFrame:(const NXRect *)frameRect
{
  NXSize interCellSpacing = {0.0, 0.0}, docSize;

  [super initFrame:frameRect];
  cellMatrix = [[Matrix alloc] initFrame:frameRect
		mode:NX_LISTMODE
		cellClass:[FooCell class]
		numRows:0
		numCols:1];

  /*
   * In the following lines,
   * remember that "cellMatrix" is the matrix that will be installed
   * in the scrollview, "self" is the scrollview.
   */

  /* we don't want any space between the matrix's cells  */
  [cellMatrix setIntercell:&interCellSpacing];
  /* resize the matrix to contain the cells */
  [cellMatrix sizeToCells];
  [cellMatrix setAutosizeCells:YES];
  /*
   * when the user clicks in the matrix and then drags the mouse out of
   * scrollView's contentView, we want the matrix to scroll
   */
  [cellMatrix setAutoscroll:YES];
  /* let the matrix stretch horizontally */
  [cellMatrix setAutosizing:NX_WIDTHSIZABLE];  
  /* Install the matrix as the docview of the scrollview */
  [[self setDocView:cellMatrix] free];
  /* set up the visible attributes of the scrollview */
  [self setVertScrollerRequired:YES];
  [self setBorderType:NX_BEZEL];
  /* tell the subviews to resize along with the scrollview */
  [self setAutoresizeSubviews:YES];
  /* This is the only way to get the clipview to resize too */
  [[cellMatrix superview] setAutoresizeSubviews:YES];
  /* Allow the scrollview to stretch both horizontally and vertically */
  [self setAutosizing:NX_WIDTHSIZABLE|NX_HEIGHTSIZABLE];
  /* Resize the matrix to fill the inside of the scrollview */
  [self getContentSize:&docSize];
  [cellMatrix sizeTo:docSize.width :docSize.height];

  return self;
}

- free
{
  [cellMatrix free];
  return [super free];
}

- cellMatrix
{
  return cellMatrix;
}

- loadCellsFrom:(List *)fooObjects
/*
 * Fill the matrix with FooCells, associate each FooCell with a FooObject.
 *
 * Since we recycle the cells (via renewRows:cols:), we also set the state
 * of each cell to 0 and unhighlight it.  If we don't do that, the recycled
 * cells will display their previous state.
 */
{
  int i, cellCount;

  cellCount = [fooObjects count];

  /* tell the matrix there are 0 cells in it (but don't deallocate them) */
  [cellMatrix renewRows:0 cols:1];
  [cellMatrix lockFocus];		/* for highlightCellAt::lit: */
  for (i=0;i<cellCount;i++) {
    FooCell *cell;
    /*
     * add a row to the matrix.  (This doesn't necessarily allocate a new
     * cell, thanks to renewRows:cols:).
     */
    [cellMatrix addRow];
    cell = [cellMatrix cellAt:i:0];
    /* make sure the cell is neither selected nor highlighted */
    [cellMatrix highlightCellAt:i:0 lit:NO];
    [cell setState:0];
    /* install the fooObject in that cell */
    [cell setFooObject:[fooObjects objectAt:i]];
  }
  [cellMatrix unlockFocus];
  [cellMatrix sizeToCells];
  [cellMatrix display];
  
  return self;
}

@end
